package com.iflytek.ci.cpms.service.impl;

import com.iflytek.ci.common.service.impl.AutobuildImpl;
import com.iflytek.ci.common.support.XMLNodeParser;
import com.iflytek.ci.cpms.domain.Milestone;
import com.iflytek.ci.cpms.domain.Project;
import com.iflytek.ci.cpms.service.MilestoneReprterService;
import com.iflytek.ci.main.dto.Prior;

import org.apache.cxf.helpers.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.internal.io.dav.DAVRepositoryFactory;
import org.tmatesoft.svn.core.internal.io.fs.FSRepositoryFactory;
import org.tmatesoft.svn.core.internal.io.svn.SVNRepositoryFactoryImpl;
import org.tmatesoft.svn.core.internal.wc.DefaultSVNOptions;
import org.tmatesoft.svn.core.wc.*;
import org.tmatesoft.svn.core.wc2.SvnOperationFactory;
import org.tmatesoft.svn.core.wc2.SvnUpgrade;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

/**
 * 里程碑报告向导数据传递的实体类 用于完成自动构建所需的脚本调用功能 使用本实体类需要先调用构造方法，以提供所需要的参数 。
 * 
 * author：mdzhang
 */
@Service("MilestoneReprterService")
public class MilestoneReprterServiceImpl implements MilestoneReprterService {
	/** 日志信息 */
	private static final Logger logger = LoggerFactory
			.getLogger(MilestoneReprterServiceImpl.class);
	private static SVNClientManager ourClientManager;
	private static SvnOperationFactory svnOperationFactory;
	/** 本地存放svn代码的文件夹位置 */
	@Value("${code_project_path}")
	private String code_path;

	/** bat脚本存放路径 */
	@Value("${bat_path}")
	private String bat_path;

	/** 调用bat脚本的命令 */
	private String bat_start = "cmd /c ";

	/** bat脚本执行的输出结果路径 */
	@Value("${log_path}")
	private String log_path;

	/** war包存档路径 */
	@Value("${war_save_path}")
	private String war_save;

	@Value("${svn_name}")
	private String name;

	@Value("${svn_psw}")
	private String password;

	// 本地代码存放路径
	private String file_path = "";

	/**
	 * 从SVN迁出代码到本地文件夹保存，若迁出失败则将保存的代码删除
	 * 
	 * @return 遷出代碼的版本號
	 */
	@SuppressWarnings({ "finally", "deprecation" })
	@Override
	public long svn_co_code(Milestone milestone, Project project) {
		DAVRepositoryFactory.setup();// 支持https和http访问模式
		SVNRepositoryFactoryImpl.setup();// 支持svn和svnxxx访问模式
		FSRepositoryFactory.setup();// 用于支持file访问模式
		long version = 0;
		file_path = code_path.concat(project.getCode())
				.concat(Prior.PATH_SPLIT)
				.concat(String.valueOf(milestone.getId()));
		// 定义版本库的svn路径
		try {
			// TODO svn路径修改为project.getSvn_url()
			SVNURL repositoryURL = SVNURL
					.parseURIEncoded("https://192.168.11.180/svn/CDMS/trunk/cdms/");
			// 本地存放代码的临时文件路径
			String myPath = code_path.concat(project.getCode())
					.concat(Prior.PATH_SPLIT)
					.concat(String.valueOf(milestone.getId()));
			File path = new File(myPath);
			// 加载驱动程序
			ISVNOptions options = SVNWCUtil.createDefaultOptions(true);
			ourClientManager = SVNClientManager.newInstance(
					(DefaultSVNOptions) options, name, password);
			SVNUpdateClient updateClient = ourClientManager.getUpdateClient();
			version = updateClient.doCheckout(repositoryURL, path,
					SVNRevision.HEAD, SVNRevision.HEAD, true);
			SvnUpgrade svnUpgrade = svnOperationFactory.createUpgrade();
			svnUpgrade.getOptions();
		} catch (SVNException e) {
			logger.debug("路径初始化失败");
			e.printStackTrace();
		} finally {
			return version;
		}
	}

	/**
	 * 执行预编译,根据返回数据判断执行是否成功
	 * 
	 * @return 执行编译结果
	 */
	@SuppressWarnings("finally")
	public boolean compile(Milestone milestone, Project project) {
		boolean result = false;
		file_path = code_path.concat(project.getCode())
				.concat(Prior.PATH_SPLIT)
				.concat(String.valueOf(milestone.getId()));
		String file_save = log_path.concat(project.getCode()).concat("-")
				.concat(String.valueOf(milestone.getId())).concat("_build.log");
		String command = bat_start.concat(bat_path).concat("mvn.bat ")
				.concat(file_path).concat(" ").concat(file_save);
		try {
			Process pro = Runtime.getRuntime().exec(command);
			InputStream in = pro.getInputStream();
			BufferedReader br = new BufferedReader(new InputStreamReader(in));
			@SuppressWarnings("unused")
			String tmp = "";
			while ((tmp = br.readLine()) != null) {
				pro.waitFor();
			}
			File file = new File(file_save);
			if (FileUtils.getStringFromFile(file).indexOf("BUILD  SUCCESS") > 0) {
				result = true;
			}
		} catch (IOException e) {
			logger.debug("创建进程并调用命令失败");
			e.printStackTrace();
		} catch (InterruptedException e) {
			logger.debug("缓存阻塞");
			e.printStackTrace();
		} finally {
			return result;
		}
	}

	/**
	 * 读取本地代码的主pom文件，查找tag路径
	 * 
	 * @return tag目录
	 */

	@SuppressWarnings("finally")
	public String getTag_url(Milestone milestone, Project project) {
		DAVRepositoryFactory.setup();// 支持https和http访问模式
		SVNRepositoryFactoryImpl.setup();// 支持svn和svnxxx访问模式
		FSRepositoryFactory.setup();// 用于支持file访问模式
		String tag_url = "";
		String node_path = "project/build/plugins/plugin/configuration/tagBase";
		try {
			// TODO 修改为project.getSvn_url()
			String pom_url = "https://192.168.11.180/svn/CDMS/trunk/cdms/";
			if (!pom_url.endsWith(Prior.PATH_SPLIT)) {
				pom_url = pom_url.concat("/pom.xml");
			} else {
				pom_url = pom_url.concat("pom.xml");
			}
			SVNURL repositoryURL = SVNURL.parseURIEncoded(pom_url);
			ISVNOptions options = SVNWCUtil.createDefaultOptions(true);
			ourClientManager = SVNClientManager.newInstance(
					(DefaultSVNOptions) options, name, password);
			SVNWCClient svncat = ourClientManager.getWCClient();
			File pom = new File(log_path.concat(
					String.valueOf(milestone.getId())).concat("_pom.xml"));
			OutputStream dst = new FileOutputStream(pom, true);// 定义文件读写流，将svnkit读取的数据写到本地文件中保存
			svncat.doGetFileContents(repositoryURL, SVNRevision.HEAD,
					SVNRevision.HEAD, false, dst);// 使用svnkit执行svn
													// cat操作，获取文件内容，并写入文件中保存
			dst.close();
			if (pom.exists() && pom.canRead()) {
				XMLNodeParser xmlparser = new XMLNodeParser();
				tag_url = xmlparser.getTextContent(pom, node_path);
				pom.delete();
			}
		} catch (SVNException e) {
			logger.debug("连接svn的tag路径失败，可能该tag不存在");
		} catch (FileNotFoundException e) {
			logger.debug("创建读写流失败");
			e.printStackTrace();
		} finally {
			return tag_url;
		}
	}

	/**
	 * 设置BuildNote号
	 * 
	 * @return 需要向RDM提交的，下一个版本的构建号
	 */
	@Override
	@SuppressWarnings("finally")
	public String setBuildNote(Milestone milestone, Project project) {
		String tag_url = getTag_url(milestone, project);
		String build_note = "BuildNote1001";
		String file_save = log_path.concat(String.valueOf(milestone.getId()))
				.concat("_getbuild.log");
		String command = bat_start.concat(bat_path).concat("svnlist.bat ")
				.concat(tag_url).concat(" ").concat(file_save);
		try {
			Process pro = Runtime.getRuntime().exec(command);
			InputStream in = pro.getInputStream();
			BufferedReader br = new BufferedReader(new InputStreamReader(in));
			@SuppressWarnings("unused")
			String tmp = "";
			while ((tmp = br.readLine()) != null) {
				pro.waitFor();
			}
			File list = new File(file_save);
			String result_list = FileUtils.getStringFromFile(list);// .replaceAll("[a-z]",
																	// // "");
			list.delete();
			if (!result_list.equals("") && result_list != null) {
				String[] svn_list = result_list.split(Prior.PATH_SPLIT);// svn中每个目录下都有“/”，将文件内容切割成数组
				int[] list_build = new int[svn_list.length];
				list_build[0] = Integer.valueOf(svn_list[0].substring(
						svn_list[0].length() - 4, svn_list[0].length()));// build_note[0]设置为svn_list[0]最后的4个字符表示的数字
				build_note = svn_list[0].replaceFirst(
						String.valueOf(list_build[0]),
						String.valueOf(list_build[0] + 1)).trim();// 将svn_list最后的四位数字加1，之后赋值给build_note
				for (int i = 1; i < svn_list.length; i++) {
					if (svn_list[i].length() >= 4) {
						list_build[i] = Integer
								.valueOf(svn_list[i].substring(
										svn_list[i].length() - 4,
										svn_list[i].length()));
						if (list_build[i] > list_build[i - 1]) {
							build_note = svn_list[i].replaceFirst(
									String.valueOf(list_build[i]),
									String.valueOf(list_build[i] + 1)).trim();
						}
					}
				}
			}
		} catch (IOException e) {
			logger.debug("创建进程并调用命令失败");
		} catch (InterruptedException e) {
			logger.debug("进程阻塞");
		} finally {
			return build_note;
		}
	}

	/**
	 * 删除本地临时保存的迁出代码
	 */
	public void delete_code(Milestone milestone, Project project) {
		file_path = code_path.concat(project.getCode())
				.concat(Prior.PATH_SPLIT)
				.concat(String.valueOf(milestone.getId()));
		String command = bat_start.concat(bat_path).concat("del.bat ")
				.concat(file_path);
		try {
			Process pro = Runtime.getRuntime().exec(command);
			InputStream in = pro.getInputStream();
			BufferedReader br = new BufferedReader(new InputStreamReader(in));
			@SuppressWarnings("unused")
			String tmp = "";
			while ((tmp = br.readLine()) != null) {
				pro.waitFor();
			}
		} catch (IOException e) {
			logger.debug("创建进程并调用命令失败");
		} catch (InterruptedException e) {
			logger.debug("缓存阻塞");
		}
	}

	/**
	 * 删除Tag信息
	 * 
	 * @param build_note
	 *            需要删除的buildnote号
	 */
	@Override
	public void delete_tag(Milestone milestone, Project project,
			String build_note) {
		String tag_url = getTag_url(milestone, project);
		DAVRepositoryFactory.setup();// 支持https和http访问模式
		SVNRepositoryFactoryImpl.setup();// 支持svn和svnxxx访问模式
		FSRepositoryFactory.setup();// 用于支持file访问模式
		try {
			// SVNURL repositoryURL = SVNURL.parseURIEncoded(tag_url);
			ISVNOptions options = SVNWCUtil.createDefaultOptions(true);
			ourClientManager = SVNClientManager.newInstance(
					(DefaultSVNOptions) options, name, password);
			SVNCommitClient svndelete = ourClientManager.getCommitClient();
			if (!tag_url.endsWith(Prior.PATH_SPLIT)) {
				tag_url = tag_url.concat(Prior.PATH_SPLIT);
			}
			SVNURL[] tag_urls = new SVNURL[1];
			tag_urls[0] = SVNURL.parseURIEncoded(tag_url.concat(build_note));
			svndelete.doDelete(tag_urls, null);
		} catch (SVNException e) {
			logger.debug("连接svn的tag路径失败，可能该tag不存在");
		}
	}

	/**
	 * 拷貝war包
	 */
	@Override
	public void copyWar(Milestone milestone, Project project) {
		file_path = code_path.concat(project.getCode())
				.concat(Prior.PATH_SPLIT)
				.concat(String.valueOf(milestone.getId()))
				.concat("/web/target/").concat("*.war ");// 需要拷贝的war包路径
		String file_save = war_save.concat(project.getCode()).concat("-")
				.concat(milestone.getName());
		String command = bat_start.concat(bat_path).concat("copy.bat ")
				.concat(file_path).concat(file_save);
		try {
			Process pro = Runtime.getRuntime().exec(command);
			InputStream in = pro.getInputStream();
			BufferedReader br = new BufferedReader(new InputStreamReader(in));
			@SuppressWarnings("unused")
			String tmp = "";
			while ((tmp = br.readLine()) != null) {
				pro.waitFor();
			}
		} catch (IOException e) {
			logger.debug("创建进程并调用命令失败");
			e.printStackTrace();
		} catch (InterruptedException e) {
			logger.debug("缓存阻塞");
			e.printStackTrace();
		}
	}

	// /**
	// * 获取changelog文件內容
	// *
	// * @return changelog文件內容
	// */
	// public String changelog(Milestone milestone, Project project) {
	// String out_put = "";
	// String file_path = code_path.concat(project.getCode())
	// .concat(Prior.PATH_SPLIT)
	// .concat(String.valueOf(milestone.getId()));
	// if (file_path.endsWith(Prior.PATH_SPLIT)) {
	// file_path = file_path.concat(Prior.PATH_SPLIT).concat(
	// "changelog.txt");
	// } else {
	// file_path = file_path.concat("changelog.txt");
	// }
	// File changelog = new File(file_path);
	// if (!changelog.exists() || !changelog.canRead()) {
	// logger.debug("文件不存在或不可读!");
	// } else {
	// out_put = FileUtils.getStringFromFile(changelog);
	// }
	// return out_put;
	// }

	/**
	 * 编译，构建，删除本地代码功能整合
	 * 
	 * @return changelog信息，为空说明编译失败或者构建失败
	 */
	@Override
	public String build(String releaseVersion, Milestone milestone,
			Project project) {
		String result = "";
		if (compile(milestone, project) == false) {
			delete_code(milestone, project);
		} else {
			file_path = code_path.concat(project.getCode())
					.concat(Prior.PATH_SPLIT)
					.concat(String.valueOf(milestone.getId()));
			String tag = setBuildNote(milestone, project);
			AutobuildImpl auto = new AutobuildImpl();
			if (auto.build(file_path, milestone.getId(), tag, releaseVersion,
					project.getCode()) != 0) {
				delete_code(milestone, project);
			} else {
				result = getChangelog(milestone, project, log_path);
				delete_code(milestone, project);
			}
		}
		return result;
	}

	/**
	 * 获取changelog文件内容
	 * 
	 * @param milestone
	 *            里程碑信息
	 * @param project
	 *            项目信息
	 * @param log_path
	 *            log所在路径
	 * @return
	 */
	@SuppressWarnings({ "finally", "deprecation" })
	public String getChangelog(Milestone milestone, Project project,
			String log_path) {
		String result = "";
		String start_time = milestone.getStarttime().toLocaleString();
		String end_time = milestone.getDuetime().toLocaleString();
		String changelog_svnurl = "";
		// 构建changelog.txt文件的svn路径
		if (project.getSvn_url().endsWith(Prior.PATH_SPLIT)) {
			changelog_svnurl = project.getSvn_url().concat("changelog.txt ");
		} else {
			changelog_svnurl = project.getSvn_url().concat(Prior.PATH_SPLIT)
					.concat("changelog.txt ");
		}
		// 用于保存该里程碑开始前的changelog文件内容
		String log_save1 = log_path.concat(String.valueOf(milestone.getId()))
				.concat("_1_changelog.txt");
		// 用于保存该里程碑结束时的changelog文件内容
		String log_save2 = log_path.concat(String.valueOf(milestone.getId()))
				.concat("_2_changelog.txt");

		// 创建脚本调用命令
		String command1 = bat_start.concat(bat_path).concat("changelog.bat ")
				.concat(start_time).concat(Prior.SPACE)
				.concat(changelog_svnurl).concat(Prior.SPACE).concat(log_save1);
		String command2 = bat_start.concat(bat_path).concat("changelog.bat ")
				.concat(end_time).concat(Prior.SPACE).concat(changelog_svnurl)
				.concat(Prior.SPACE).concat(log_save2);
		try {
			for (int i = 0; i < 2; i++) {
				if (i == 0) {
					Process pro = Runtime.getRuntime().exec(command1);
					InputStream in = pro.getInputStream();
					BufferedReader br = new BufferedReader(
							new InputStreamReader(in));
					@SuppressWarnings("unused")
					String tmp = "";
					while ((tmp = br.readLine()) != null) {
						pro.waitFor();
					}
					// 获取文件内容并赋值给log_save1保存
					File changelog_start = new File(log_save1);
					log_save1 = FileUtils.getStringFromFile(changelog_start);
					changelog_start.delete();
				} else {
					Process pro = Runtime.getRuntime().exec(command2);
					InputStream in = pro.getInputStream();
					BufferedReader br = new BufferedReader(
							new InputStreamReader(in));
					@SuppressWarnings("unused")
					String tmp = "";
					while ((tmp = br.readLine()) != null) {
						pro.waitFor();
					}
					// 获取文件内容并赋值给log_save2保存
					File changelog_end = new File(log_save2);
					log_save2 = FileUtils.getStringFromFile(changelog_end);
					changelog_end.delete();
				}
			}
			// 取出log_save2中存在而log_save1不存在的数据，作为开发/修改范围
			result = log_save2.replaceAll(log_save1, "");
		} catch (IOException e) {
			logger.debug("创建进程并调用命令失败");
			e.printStackTrace();
		} catch (InterruptedException e) {
			logger.debug("缓存阻塞");
			e.printStackTrace();
		} finally {
			return result;
		}
	}
}
